package com.vader.boot.applicationContext;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.Controller;

/**
 * @author Vader
 * @date 2022/3/23
 **/
@SpringBootApplication
@Slf4j
public class ApplicationContextApplication {
    public static void main(String[] args) {
//        testClassPathXmlApplicationContext();
//        testFileSystemXmlApplicationContext();
//        testAnnotationConfigApplicationContext();
        testAnnotationConfigApplicationContext();

//        DefaultListableBeanFactory beanFactory = new DefaultListableBeanFactory();
//        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
//            log.info("before" + beanDefinitionName);
//        }
//
//        XmlBeanDefinitionReader xmlBeanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
//        xmlBeanDefinitionReader.loadBeanDefinitions(new ClassPathResource("b01.xml"));
//        for (String beanDefinitionName : beanFactory.getBeanDefinitionNames()) {
//            log.info("after" + beanDefinitionName);
//        }
    }

    /**
     * 根据classpath寻找xml文件
     */
    private static void testClassPathXmlApplicationContext() {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("b01.xml");
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("----" + beanDefinitionName);
        }
        log.info(context.getBean(Bean2.class).getBean1().toString());
    }

    /**
     * 根据文件路径寻找xml文件
     */
    private static void testFileSystemXmlApplicationContext() {
        FileSystemXmlApplicationContext context = new FileSystemXmlApplicationContext("spring-boot/src/main/resources/b01.xml");
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("----" + beanDefinitionName);
        }
        log.info(context.getBean(Bean2.class).getBean1().toString());
    }

    /**
     * 根据注解创建bean
     */
    private static void testAnnotationConfigApplicationContext() {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("----" + beanDefinitionName);
        }
        log.info(context.getBean(Bean2.class).getBean1().toString());
    }

    /**
     * 根据java配置类创建bean
     */
    private static void testAnnotationConfigServletWebServerApplicationContext() {
        AnnotationConfigServletWebServerApplicationContext context = new AnnotationConfigServletWebServerApplicationContext();
        for (String beanDefinitionName : context.getBeanDefinitionNames()) {
            log.info("----" + beanDefinitionName);
        }
        log.info(context.getBean(Bean2.class).getBean1().toString());
    }

    @Configuration
    static class WebConfig {
        @Bean
        public ServletWebServerFactory servletWebServerFactory() {
            return new TomcatServletWebServerFactory();
        }

        @Bean
        public DispatcherServlet dispatcherServlet() {
            return new DispatcherServlet();
        }

        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        @Bean
        public Controller controller1(){
            return (request, response) -> {
                response.getWriter().println("test");
                return null;
            };
        }
    }

    @Configuration
    static class Config {

        @Bean
        public Bean1 bean1() {
            return new Bean1();
        }

        @Bean
        public Bean2 bean2(Bean1 bean1) {
            Bean2 bean2 = new Bean2();
            bean2.setBean1(bean1);
            return bean2;
        }
    }

    static class Bean2 {

        private Bean1 bean1;

        public void setBean1(Bean1 bean1) {
            this.bean1 = bean1;
        }

        public Bean1 getBean1() {
            return bean1;
        }
    }

    static class Bean1 {
    }

}
